%{

#include <stack>
#include <list>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <string.h>

#include "commun.h"
#include "DTD_Document.h"
#include "DTD_Attribut.h"
#include "DTD_Element.h"
#include "DTD_Contenu.h"
#include "DTD_Any.h"
#include "DTD_Empty.h"
#include "DTD_Choix.h"
#include "DTD_PCDATA.h"
#include "DTD_Sequence.h"
#include "DTD_Simple.h"
#include "DTD_Type.h"
#include "DTD_Complex.h"
#include "DTD_TypeSimple.h"
#include "DTD_Enum.h"
#include "DTD_Mixed.h"
#include "DTD_Normal.h"
#include "dtd.tab.h"

using namespace std;

void yyerror( char * msg );
int yywrap( void );
int yylex( void );

static DTD_Document * dtd_tree;

%}

%union
{
	char c;
	char * s;
	DTD_Document * document;
	DTD_Contenu * content;
	DTD_Complex * complex;
	DTD_Sequence * sequence;
	DTD_Choix * choice;
	DTD_Mixed * mixed;
	DTD_Normal * normal;
	DTD_Attribut * attribut;
	DTD_Type * type;
	DTD_Enum * enumeration;
	Attributes * attributes;
	Contents * contents;
	Enums * enums;
}

%token ELEMENT ATTLIST CLOSE OPENPAR CLOSEPAR COMMA PIPE AST QMARK PLUS CDATA FIXED PCDATA ANY EMPTY
%token <s> NAME TOKENTYPE DECLARATION STRING

%type <document> dtd
%type <content> elm_definition
%type <complex> contenu
%type <sequence> sequence
%type <choice> choice
%type <mixed> mixed
%type <normal> item
%type <contents> liste_sequence liste_choix_plus liste_choix
%type <attributes> att_definition
%type <c> card
%type <attribut> attribut
%type <type> att_type
%type <enumeration> type_enumere
%type <enums> liste_enum_plus liste_enum
%type <s> defaut_declaration item_enum

%%

dtd :
	dtd ELEMENT NAME elm_definition CLOSE
	{
		$$ = $1;
		$$->addElement( new DTD_Element( $3, $4 ) );
	}
|	dtd ATTLIST NAME att_definition CLOSE
	{
		$$ = $1;
		$$->addAttributes( $3, $4 );
	}	
|	/* empty */
	{ 
		$$ = new DTD_Document();
		dtd_tree = $$;
	}                  
;

elm_definition :
	contenu
	{
		$$ = $1;
	}
|	mixed
	{
		$$ = $1;
	}
|	OPENPAR PCDATA CLOSEPAR
	{
		$$ = new DTD_PCDATA();
	}
|	ANY
	{
		$$ = new DTD_Any();
	}
|	EMPTY
	{
		$$ = new DTD_Empty();
	}
;

contenu :
	sequence
	{
		$$ = $1;
	}
|	choice
	{
		$$ = $1;
	}
;

sequence :
	OPENPAR liste_sequence CLOSEPAR
	{
		$$ = new DTD_Sequence( $2 );
	}
;

liste_sequence :
	item
	{
		$$ = new vector<DTD_Normal *>;
		$$->push_back( $1 );
	}
|	liste_sequence COMMA item
	{
		$$ = $1;
		$$->push_back( $3 );
	}
;

item :
	NAME card
	{
		$$ = new DTD_Simple( $1, $2 );
	}
|	contenu card
	{
		$$ = $1;
		$$->setCard( $2 );
	}
;

card :
	AST
	{
		$$ = '*';
	}
|	QMARK
	{
		$$ = '?';
	}
|	PLUS
	{
		$$ = '+';
	}
|	/* vide */
	{
		$$ = 0;
	}
;

choice :
	OPENPAR liste_choix_plus CLOSEPAR
	{
		$$ = new DTD_Choix( $2 );
	}
;

liste_choix_plus :
	liste_choix PIPE item
	{
		$$ = $1;
		$$->push_back( $3 );
	}
;
	
liste_choix :
	item
	{
		$$ = new vector<DTD_Normal *>;
		$$->push_back( $1 );
	}
|	liste_choix PIPE item
	{
		$$ = $1;
		$$->push_back( $3 );
	}
;

mixed :
	choice AST
	{
		$$ = new DTD_Mixed( $1 );
	}
;

att_definition :
	att_definition attribut
	{
		$$ = $1;
		$$->push_back( $2 );
	}
|	/* empty */
	{
		$$ = new vector<DTD_Attribut *>;
	}
;

attribut :
	NAME att_type defaut_declaration
	{
		$$ = new DTD_Attribut( $1, $2, $3 );
	}
;

att_type :
	CDATA
	{
		$$ = new DTD_TypeSimple( "CDATA" );
	}
|	TOKENTYPE
	{
		$$ = new DTD_TypeSimple( "NMTOKEN" );
	}
|	type_enumere
	{
		$$ = $1;
	}
;

type_enumere :
	OPENPAR liste_enum_plus CLOSEPAR
	{
		$$ = new DTD_Enum( *$2 );
	}
;

liste_enum_plus :
	liste_enum PIPE item_enum
	{
		$$ = $1;
		$$->push_back( $3 );
	}
;

liste_enum :
	item_enum
	{
		$$ = new vector<string>;
		$$->push_back( $1 );
	}
|	liste_enum PIPE item_enum
	{
		$$ = $1;
		$$->push_back( $3 );
	}
;

item_enum :
	NAME
;

defaut_declaration :
	DECLARATION 
|	STRING     
|	FIXED STRING
	{
		char fixed[] = "#FIXED ";
		$$ = strcat( fixed, $2 );
	}
;

%%

DTD_Document * getDTDTree()
{
	return dtd_tree;
}

int dtdwrap( void )
{
	return 1;
}

void dtderror( char * msg )
{
	fprintf( stderr, "%s\n", msg );
}
